package com.rocky.component.elasticsearch;

import com.rocky.component.elasticsearch.model.RockyDocumentWrapper;
import com.rocky.component.elasticsearch.service.RockyDocumentService;
import com.rocky.component.elasticsearch.service.RockyIndexService;
import com.rocky.component.model.GeoStoreEntity;
import com.rocky.component.util.ObjectMapperUtil;
import lombok.RequiredArgsConstructor;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.geo.GeoPoint;
import org.elasticsearch.common.text.Text;
import org.elasticsearch.common.unit.DistanceUnit;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.script.Script;
import org.elasticsearch.script.ScriptType;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.io.IOException;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;

/**
 * @author rocky
 * date 2025-07-24
 * Description:
 */
@RestController
@RequiredArgsConstructor
@RequestMapping("/geoQueryExample")
public class GeoQueryExample {

    private final RestHighLevelClient restHighLevelClient;

    private final RockyIndexService rockyIndexService;

    private final RockyDocumentService rockyDocumentService;

    private static final String index = "rocky_store";

    @GetMapping("/test")
    public void test() throws IOException {
//        System.out.println(rockyIndexService.delete("rocky_store_temp"));


        GeoStoreEntity geoStoreEntity = new GeoStoreEntity();
        geoStoreEntity.setName("杭州诚适口腔门诊部有限公司");
        geoStoreEntity.setAddress("杭州市拱墅区萍水街470、472号诚适口腔门诊部");
        geoStoreEntity.setProvince("浙江");
        geoStoreEntity.setCity("杭州");
        geoStoreEntity.setCounty("拱墅");
        geoStoreEntity.setCreateDate(LocalDate.now());
        geoStoreEntity.setUpdateTime(LocalDateTime.now());

        geoStoreEntity.setId("1807705652924256280");
        geoStoreEntity.setLatitude(new BigDecimal("30.306922"));
        geoStoreEntity.setLongitude(new BigDecimal("120.113586"));
        geoStoreEntity.setLocation(geoStoreEntity.getLatitude() + "," + geoStoreEntity.getLongitude());
        geoStoreEntity.setVersion(1);
        boolean updateResult = rockyDocumentService.index(
                new RockyDocumentWrapper()
                        .setId(geoStoreEntity.getId())
                        .setVersion(geoStoreEntity.getVersion())
                        .setBody(geoStoreEntity)
        );
        System.out.println(updateResult);

//        System.out.println(rockyDocumentService.delete("rocky_store_temp", "1807705652924256280", 0L));
    }

    @GetMapping("/saveOrUpdate")
    public String saveOrUpdate() throws IOException {
        GeoStoreEntity geoStoreEntity = new GeoStoreEntity();
        geoStoreEntity.setName("杭州诚适口腔门诊部有限公司");
        geoStoreEntity.setAddress("杭州市拱墅区萍水街470、472号诚适口腔门诊部");
        geoStoreEntity.setProvince("浙江");
        geoStoreEntity.setCity("杭州");
        geoStoreEntity.setCounty("拱墅");
        geoStoreEntity.setCreateDate(LocalDate.now());
        geoStoreEntity.setUpdateTime(LocalDateTime.now());

        geoStoreEntity.setId("1807705652924256280");
        geoStoreEntity.setLatitude(new BigDecimal("30.306922"));
        geoStoreEntity.setLongitude(new BigDecimal("120.113586"));
        geoStoreEntity.setLocation(geoStoreEntity.getLatitude() + "," + geoStoreEntity.getLongitude());
        geoStoreEntity.setVersion(0);

//        GeoStoreEntity geoStoreEntity = new GeoStoreEntity();
//        geoStoreEntity.setName("茗芽口腔(万和门诊部)");
//        geoStoreEntity.setAddress("灯塔巷18号");
//        geoStoreEntity.setProvince("浙江");
//        geoStoreEntity.setCity("杭州");
//        geoStoreEntity.setCounty("拱墅");
//        geoStoreEntity.setCreateDate(LocalDate.now());
//        geoStoreEntity.setUpdateTime(LocalDateTime.now());
//
//        geoStoreEntity.setId("1807705652924256287");
//        geoStoreEntity.setLatitude(new BigDecimal("30.316864"));
//        geoStoreEntity.setLongitude(new BigDecimal("120.176290"));
//        geoStoreEntity.setLocation(geoStoreEntity.getLatitude() + "," + geoStoreEntity.getLongitude());
//        geoStoreEntity.setVersion(0);

        return ObjectMapperUtil.jsonString(rockyDocumentService.index(new RockyDocumentWrapper()
                .setId(geoStoreEntity.getId())
                .setVersion(geoStoreEntity.getVersion())
                .setBody(geoStoreEntity)));
    }

    @GetMapping("/find")
    public String find() throws IOException {
        BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery()
                .must(QueryBuilders.multiMatchQuery("拱墅区", "name", "address"))
                .must(QueryBuilders.termQuery("province.keyword", "浙江"))
                .filter(QueryBuilders.geoDistanceQuery("location")
                        .point(new GeoPoint(30.331779, 120.192954))
                        .distance(50, DistanceUnit.KILOMETERS)
                );

        Map<String, Object> params = new HashMap<>();
        params.put("lat", 30.331779);
        params.put("lon", 120.192954);
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder()
                .query(queryBuilder)
                .sort(SortBuilders.geoDistanceSort("location", new GeoPoint(30.331779, 120.192954))
                        .order(SortOrder.ASC)
                        .unit(DistanceUnit.KILOMETERS)
                )
                .scriptField("distance", new Script(ScriptType.INLINE, "painless", "doc['location'].arcDistance(params.lat, params.lon)", params))
                .highlighter(new HighlightBuilder().requireFieldMatch(false)
                        .field(new HighlightBuilder.Field("name"))
                        .field(new HighlightBuilder.Field("address"))
                        .preTags("<span style=color:red>")
                        .postTags("</span>")
                )
                .fetchSource("*", null)
                .from(0)
                .size(10);

        SearchRequest searchRequest = new SearchRequest(index)
                .source(searchSourceBuilder);

        SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
        for (SearchHit hit : searchResponse.getHits().getHits()) {
            Map<String, HighlightField> highlightFields = hit.getHighlightFields();
            if (highlightFields.containsKey("name")) {
                System.out.println("name中有这个字段");
                Text[] names = highlightFields.get("name").getFragments();
                for (Text name : names) {
                    System.out.println(name);
                }
            }

            if (highlightFields.containsKey("address")) {
                System.out.println("address中有这个字段");
                Text[] addresses = highlightFields.get("address").getFragments();
                for (Text address : addresses) {
                    System.out.println(address);
                }
            }
        }

        return ObjectMapperUtil.jsonString(searchResponse.getHits());
    }
}
